package com.loghead
{
	import com.loghead.events.LogHeadEvent;
	import com.loghead.utils.LogUtils;
	
	import flash.events.EventDispatcher;
			
	public class LogBase extends EventDispatcher
	{
		//Constants
		public static var searchStr:String = "";
		
		public static const highLightText:String;
		
		public static var SEARCH_COLOR:String = "#cc77cc";
		
		public static var DETAIL_COLOR:String = "#aaaaaa"; 
		
		public static var FONT_NAME:String = "Arial";
		
		public static var FONT_SIZE:int = 12;
			
		
		private var _message:String;
		
		private var _fileName:String;
		
		private var _lineNumber:int = -1;
		
		private var _callingClass:String;
		
		private var _callingLine:String;
		
		private var _callingFunction:String;
		
		private var _type:LogType = LogType.INFO;
		
		private var _color:int;
		
		private var _detailHtml:String;
		
		private var _html:String;
		
		//Search vars
		private var _searchMode:Boolean;
		private var _searchLen:int = 0;
		private var _detailMatch:int = -1;
		private var _messageMatch:int = -1;
		
		private var _detailHeader:String;
		
		public var startIndex:int = -1;
		public var endIndex:int = -1;
						
		public function LogBase( message:String , type:LogType, callingClass:String = "", callingFunction:String = "", callingLine:String = "", color:int = 0 )
		{
			_message = message;
			_callingLine = callingLine;
			_callingClass = callingClass;
			_callingFunction = callingFunction;
			_color = color; 
			_type = type;
			
			//Initialize our html strings
			_detailHeader = buildDetailHeader();	
			_detailHtml = buildDetailHtml();
			_html = buildHtml();	
		}
				
		private function buildDetailHtml():String
		{			
			var tempHtml:String;
			
			if( _detailMatch > -1 )
			{				
				tempHtml = buildDetailFont( _detailHeader.substring( 0, _detailMatch )) 
							+ buildSearchFont( _detailHeader.substring( _detailMatch, _detailMatch + _searchLen )) 
							+ buildDetailFont( _detailHeader.substring( _detailMatch + _searchLen ));							
			}	
			else
				tempHtml = buildDetailFont( _detailHeader ) ;
			
			tempHtml += buildHtmlPiece();
						
			return buildParagraph( tempHtml )				
		}
						
		private function buildHtml():String
		{				
			return buildParagraph( buildHtmlPiece() );	
		}
		
		private function buildHtmlPiece():String
		{
			var tempHtml:String;
			if( _messageMatch > -1 )
			{
				tempHtml = buildMessageFont( _message.substring( 0, _messageMatch )) 
							+ buildSearchFont( _message.substring( _messageMatch, _messageMatch + _searchLen )) 
							+ buildMessageFont( _message.substring( _messageMatch + _searchLen ));
			}			
			else
				tempHtml = buildMessageFont( _message );;
			
			return tempHtml;
		}
		
		private function buildParagraph( str:String ):String
		{
			return '<P ALIGN="LEFT"><B>' + str + '</B></P>';
		}
		
		public function setValues( message, callingClass:String = "", callingFunction:String = "", callingLine:String = "", color:int = 0 )
		{
			_message = message;
			_callingLine = callingLine;
			_callingClass = callingClass;
			_callingFunction = callingFunction;
			_color = color; 
		}	
		
		public function get html():String
		{
			return _html;
		}
		
		public function get detailedHtml():String
		{
			return _detailHtml;
		}
		
		public function get detailedMessage():String
		{
			return detailHeader + _message;
			
		}
		
		private function buildDetailHeader():String
		{
			var classString:String = _callingClass == "" ? "" : _callingClass + " : ";
			var lineString:String = _callingLine == "" ? "" : " [" + _callingLine + "]"  + ": ";
			return "\n" +  classString  + _callingFunction + lineString;
		}
		
		public function get detailHeader():String
		{
			return _detailHeader;
		}		
				
		public function searchForString( str:String, searchDetails:Boolean ):Boolean
		{
			
			if( !str || str == "" )
			{
				clearSearch();
				return false;
			}
			
			_searchLen = str.length;
			
			var hasString:Boolean;
			if( searchDetails )
			{
				_detailMatch = detailHeader.toLowerCase().indexOf( str );
				if( _detailMatch > -1 )
				{
					hasString = true;
					_searchMode = true;
				}
			}
			_messageMatch = _message.toLowerCase().indexOf( str );
			if( _messageMatch > -1 )
			{
				hasString = true;
				_searchMode = true;
			}
			
			_detailHtml = buildDetailHtml();
			_html = buildHtml();			
			
			return hasString;	
		}
		
		public function clearSearch():void
		{
			_searchMode = false;
			_messageMatch = -1;
			_detailMatch = -1;
			_searchLen = 0;
			_detailHtml = buildDetailHtml();
			_html = buildHtml();
		}
		
		private function buildSearchFont( str:String ):String
		{
			return LogUtils.buildFontString( str, SEARCH_COLOR, 14 );
		}
		
		private function buildMessageFont( str:String ):String
		{
			return LogUtils.buildFontString( str, type.colorString );
		}
		
		private function buildDetailFont( str:String ):String
		{
			return LogUtils.buildFontString( str, DETAIL_COLOR );
		}
		
		
		
		private function intToHex( number ):String
		{
			var hex_chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
			// the output, supports only 32-bit integers
			var out = ['0', '0', '0', '0', '0', '0', '0', '0'];
			var len = out.length;
			for (var i = 0; i < len; i++) {
				var n = number >> 4;
				out[len - i - 1] = hex_chars[number - (n << 4)];
				number = n;
			}
			
			return "#" + out.join("");
		}
		
		// message getter
		public function get message():String  
		{ return _message; }
		
		// message setter
		public function set message( newVal:String ):void  { _message = newVal; dispatchUpdateEvent();}
		
		// color getter
		public function get color():int  { return _color; }
		
		// color setter
		public function set color( newVal:int ):void  { _color = newVal; dispatchUpdateEvent();}
		
		// callingLine getter
		public function get callingLine():String  { return _callingLine; }
		
		// callingLine setter
		public function set callingLine( newVal:String ):void  { _callingLine = newVal; dispatchUpdateEvent();}
		
		// callingClass getter
		public function get callingClass():String  { return _callingClass; }
		
		// callingClass setter
		public function set callingClass( newVal:String ):void  { _callingClass = newVal; dispatchUpdateEvent();}
		
		// callingFunction getter
		public function get callingFunction():String  { return _callingFunction; }
		
		// callingFunction setter
		public function set callingFunction( newVal:String ):void  { _callingFunction = newVal; dispatchUpdateEvent(); }
		
		// lineNumber getter
		public function get lineNumber():int  { return _lineNumber; }
		
		// lineNumber setter
		public function set lineNumber( newVal:int ):void  { _lineNumber = newVal; }
		
		// type getter
		public function get type():LogType  { return _type; }
		
		// type setter
		public function set type( newVal:LogType ):void  { _type = newVal; }
				
		private function dispatchUpdateEvent():void
		{
			var e:LogHeadEvent = new LogHeadEvent( LogHeadEvent.LOG_UPDATED );
			dispatchEvent( e );
		}
		
	}
}